package com.weixin.xplore.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;

import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Description:
 * @Version: 1.0.0
 */
@UtilityClass
public class JsonUtil {

    /**
     * 日期格式
     */
    public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 序列化与反序列化的Mapper
     */
    private static ObjectMapper objectMapper;

    static {
        //在获取不到就自定义
        if (null == objectMapper) {
            objectMapper = new ObjectMapper();
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            objectMapper.setDateFormat(new SimpleDateFormat(DATE_FORMAT_PATTERN));
            objectMapper.setTimeZone(TimeZone.getDefault());

            JavaTimeModule javaTimeModule = new JavaTimeModule();
            // 设置序列化格式
            javaTimeModule.addSerializer(LocalDateTime.class,
                    new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN)));

            objectMapper.registerModule(javaTimeModule);
//            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
            objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
            objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, false);
            objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
            objectMapper.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES.mappedFeature(), true);
            objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }

    }

    public static ObjectMapper objectMapper() {
        return objectMapper;
    }

    /**
     * 转成字符串
     *
     * @param source
     * @return
     */
    @SneakyThrows
    public static String toStr(Object source) {
        if (null == source) {
            return null;
        }

        if (source instanceof String) {
            return (String) source;
        }
        return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(source);
    }

    @SneakyThrows
    public static <T, R> Map<T, R> toMap(String json, Class p1, Class p2) {
        return objectMapper.readValue(json, objectMapper.getTypeFactory().constructParametricType(LinkedHashMap.class, p1, p2));
    }

    @SneakyThrows
    public static Map<String, Object> toMap(Object json) {
        if(json instanceof Map jm){
            return jm;
        }
        return toMap(json, String.class, Object.class);
    }

    @SneakyThrows
    public static <T> T toMap(Object json, Class p1, Class p2) {
        return json instanceof String ? (T) toMap(escape((String) json), p1, p2) : objectMapper.convertValue(json, objectMapper.getTypeFactory().constructParametricType(LinkedHashMap.class, p1, p2));
    }

    public String escape(String str) {

        return str;
    }

    /**
     * 获取一个javaType
     *
     * @param type
     * @return
     */
    @SneakyThrows
    public static JavaType getJavaType(Type type) {
        return objectMapper.getTypeFactory().constructType(type);
    }

    @SneakyThrows
    public static <T, R> List<Map<T, R>> toMapList(Object json, Class p1, Class p2) {
        JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, LinkedHashMap.class);
        return json instanceof String ? (List) objectMapper.readValue((String) json, javaType) : (List) objectMapper.convertValue(json, javaType);
    }

    @SneakyThrows
    public static <T> List<T> toList(Object json, Class<T> ct) {
        if (null == json) {
            return Collections.emptyList();
        }
        JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, ct);
        return json instanceof String ? (List) objectMapper.readValue((String) json, javaType) : (List) objectMapper.convertValue(json, javaType);
    }

    @SneakyThrows
    public static <T> List<T> toList(Object o, Type type) {
        JavaType valueType = objectMapper.getTypeFactory().constructType(type);
        List list = o instanceof String ? (List) objectMapper.readValue((String) o, valueType) : (List) objectMapper.convertValue(o, valueType);

        if (null != list && list.size() > 0) {
            for (Object t : list) {
                if (null != t) {

                }
            }
        }
        return list;

    }

    /**
     * 转换成一个bean
     *
     * @param json
     * @param p1
     * @return
     */
    @SneakyThrows
    public static <T> T toBean(String json, JavaType p1) {
        if (null == json || "".equals(json)) {
            return null;
        }
        return objectMapper.readValue(json, p1);
    }

    /**
     * JSON字符串转为实体类对象，转换异常将被抛出
     *
     * @param <T>        Bean类型
     * @param jsonString JSON字符串
     * @param beanClass  实体类对象
     * @return 实体类对象
     * @since 3.1.2
     */
    public static <T> T toBean(String jsonString, Class<T> beanClass) {
        return toBean(jsonString, getJavaType(beanClass));
    }

    public static <T> T toBean(Object jsonString, Class<T> beanClass) {
        if (null == jsonString) {
            return null;
        }
        T t = jsonString instanceof String ? toBean((String) jsonString, beanClass) : objectMapper.convertValue(jsonString, getJavaType(beanClass));
        if (null != t) {

        }
        return t;
    }

    public static <T> T toBean(Object jsonString, TypeReference<T> beanClass) {
        return jsonString instanceof String ? toBean((String) jsonString, beanClass) : objectMapper.convertValue(jsonString, beanClass);
    }

    @SneakyThrows
    public static <T> T toBean(String jsonStr, TypeReference<T> valueTypeRef) {
        T t = objectMapper.readValue(jsonStr, valueTypeRef);
        if (null != t) {

        }
        return t;
//        return objectMapper.readValue(json, p1);
    }

    @SneakyThrows
    public static <T> T beanToBean(Object json, TypeReference<T> p1) {
        return json instanceof String ? objectMapper.readValue((String) json, p1) : objectMapper.convertValue(json, p1);
    }

    @SneakyThrows
    public static JsonNode readTree(String str) {
        return objectMapper.readTree(str);
    }

    @SneakyThrows
    public static <T> T toBean(Object o, Type type) {
        JavaType valueType = objectMapper.getTypeFactory().constructType(type);
        T t = o instanceof String ? objectMapper.readValue((String) o, valueType) : objectMapper.convertValue(o, valueType);
        if (null != t) {

        }
        return t;
    }

    /**
     * 是否是一个json字符串
     *
     * @param st
     * @return
     */
    public static Boolean isJsonStr(String st) {
        if (st == null) {
            return null;
        }
//        if (!JSONUtil.isJson(st)) {
//            return null;
//        }
        try {
            return objectMapper.readTree(st) != null;
        } catch (JsonProcessingException e) {
            return false;
        }
    }
}
